/*
 * @Author: 0x9DEFA478
 * @Date: 2024-07-16 21:01:38
 * @LastEditTime: 2024-08-12 20:23:37
 * @LastEditors: 0x9DEFA478
 * @Description: 
 * QQ:2652450237
 * ============================================================================================================================================
 * 
 * 
 * 
 *                                                                                               ************      ****************************
 *                                                                                             ************      ****************************  
 *                                                                                           ************      ****************************    
 *                                                                                         ************      ****************************      
 *                                                                                       ************      ************                        
 *                                                                                     ************      ************                          
 *                                                                                   ************      ************                            
 *                                                                                 ************      ************                              
 *                                                                               ************      ************                                
 *                                                                             ************      ************                                  
 *                                                                           ************      ************                                    
 *                                                                         ************      ************                                      
 *                                                                       ************      ************                                        
 *                                                                     ************      ************                                          
 *                                                                   ************      ************                                            
 *                                                                 ************      ************                                              
 *                                                               ************      ************                                                
 *                                                             ************      ************                                                  
 *                                                           ************      ************                                                    
 *                                                         ************      ************                                                      
 *                                                       ************      ************                                                        
 *                                                     ************      ************                                                          
 *                                                   ************      ************                                                            
 *                                                 ************      ************                                                              
 *                                               ************      ************                                                                
 *                                             ************      ************                                                                  
 *                                           ************      ************                                                                    
 *                                         ************      ************                                                                      
 *                                       ************      ************                                                                        
 *                                     ************      ************                                                                          
 *                                   ************      ************                                                                            
 *                                 ************      ************                                                                              
 *                               ************      ************                                                                                
 *                             ************      ************                                                                                  
 *                           ************      ************                                                                                    
 *                         ************      ************                                                                                      
 *       ****************************      ************                                                                                        
 *     ****************************      ************                                                                                          
 *   ****************************      ************                                                                                            
 * ****************************      ************                                                                                              
 * 
 * 
 * 
 * ============================================================================================================================================
 * 
 */
#ifndef hLL_H_TS_LL_Core_H_
#define hLL_H_TS_LL_Core_H_
#include "../API/H_TS_Thread.h"
#include "./H_TS_LL_AtomicAccess.h"




/**
 * 
 * 调度响应: 并不完全指软件中断，而是由软件中断执行的关于就绪线程更新的代码；
 *          通过变量SchedulerSuspend可以挂起调度，不进行线程链表的更改
 * Tick响应：并不完全指Tick中断，而是由Tick中断执行的关于时间的代码；
 *          通过SysTickSuspend变量可以让其停止对执行任何关于时间的代码
 * 
 * 调度响应会挂起Tick响应来访问受保护的数据
 * 线程会挂起调度响应来访问受保护的数据
 * 
 * 下述链表：
 *    ReadyThreads
 *    SubReadyThreads
 *    BlockThreads
 *    SleepThreads
 *    TimeBlockThreads
 *    ExitThreads
 * 使用挂起调度的方式进行保护; H_TS实现中, 其他中断不会修改这些链表
 * 
 * 下述链表：
 *    Block_IRQUnblockThreads
 *    TimeBlock_IRQUnblockThreads
 * 使用基于平台的实现来进行安全访问，对于H_TS，其只是一个无限容量的不指定进出顺序的队列，只进行节点添加与移除
 * 为了实现无限容量、安全访问的特性，其内部数据结构一般是单向链表
 * 
 * 
 * 
 */




typedef struct{
  H_TS_Thread* volatile CurrentThread;                            //指向当前正在运行的线程。其必须是第一个结构体成员
  
  volatile Hsize SchedulerSuspend;                                //当此段不为0时挂起线程调度
  volatile Hsize SysTickSuspend;                                  //当此段不为0时停止响应定时器回调事件
  volatile Hsize SchedulerForISR;                                 //当此段不为0时有中断请求调用PendSV
  volatile Hsize ResumeSchedulerDone;                             //当恢复调度成功后, 该段被置零

#if vH_TS_IsEnableSimpleTick==0
  volatile H_TS_Tick MissTickCount;
#endif
  
  H_TS_Thread* volatile ReadyThreads;                             //就绪线程链表
  H_TS_Thread* volatile SubReadyThreads;                          //副就绪线程链表 能使高优先级的线程免于因为低优先级解阻塞导致过多查询链表的麻烦 用于快速放置低优先级的就绪线程(直接添加到头部 不进行排序, 在SubReadyThreads有高于ReadyThreads优先级的线程时才开始排序添加到ReadyThreads)
  volatile Hsize SubReadyThreadsHighestPriority;                  //副就绪线程链表中最高优先级的线程的优先级 当SubReadyThreads不为NULL时有效

  H_TS_Thread* volatile Block_IRQUnblockThreads;                  //待解阻塞链表 一般情况下只有中断会更新这个表
  volatile Hsize SleepThreadsEvent;                               //阻塞链表(睡眠)有需要解阻塞的线程
  H_TS_Thread* volatile TimeBlock_IRQUnblockThreads;              //待解阻塞链表(时间限制) 一般情况下只有中断会更新这个表

  H_TS_Thread* volatile BlockThreads;                             //阻塞线程链表
  H_TS_Thread* volatile SleepThreads;                             //睡眠线程链表
  H_TS_Thread* volatile TimeBlockThreads;                         //时间限制阻塞线程链表

  H_TS_Thread* volatile ExitThreads;                              //等待结束的线程链表
  H_TS_Thread* volatile WaitAddThreads;                           //等待添加到Threads中的线程

  H_TS_Thread* volatile Threads;                                  //所有线程


  H_TS_Thread* IdleThread;                                        //空闲线程句柄
  volatile Hsize IdleThreadResume;
  void (* volatile IdleProcess)(void*);

  volatile H_TS_Tick RunningTick;                                 //系统运行的Tick数

  volatile Hsize CPU_Load;                                        //CPU占用率
#if vH_TS_IsEnableCPULoadCalculate != 0
  volatile H_TS_RunTime CPU_Load_RunningTime;                     //总运行时间, 到达一定值后清零, 用于统计CPU占用率
#endif


  //内存管理函数集合
  struct{
    void* (*Malloc)(Hsize);
    void (*Free)(void*);
  }Memory;

}H_TS_LL_Core;


extern H_TS_LL_Core H_TS_LL_Core_Instance;


//获取系统运行的Tick数
#define H_TS_LL_GetRunningTick()                                  (H_TS_LL_Core_Instance.RunningTick)

//获取当前线程句柄
#define cH_TS_LL_ThisThread(in_Core_Instance)                     ((in_Core_Instance).CurrentThread)

//添加线程到解阻塞链表
#define H_TS_LL_AddThreadToBlock_IRQUnblockThreads(in_Thread) \
do{\
  oH_TS_LL_CompileBarrier();\
  if(H_TS_LL_AtomicAccess_SetValue(&(in_Thread)->IsIRQUnblock,-1)==0){\
    H_TS_LL_AtomicAccess_ListPush((void* volatile*)&H_TS_LL_Core_Instance.Block_IRQUnblockThreads,in_Thread,cH_TS_LL_OffsetOfStructMember(H_TS_Thread,IRQUnblockList.Next));\
  }\
  oH_TS_LL_CompileBarrier();\
}while(0)

//添加线程到解阻塞(时间限制)链表
#define H_TS_LL_AddThreadToTimeBlock_IRQUnblockThreads(in_Thread) \
do{\
  oH_TS_LL_CompileBarrier();\
  if(H_TS_LL_AtomicAccess_SetValue(&(in_Thread)->IsIRQUnblock,-1)==0){\
    H_TS_LL_AtomicAccess_ListPush((void* volatile*)&H_TS_LL_Core_Instance.TimeBlock_IRQUnblockThreads,in_Thread,cH_TS_LL_OffsetOfStructMember(H_TS_Thread,IRQUnblockList.Next));\
  }\
  oH_TS_LL_CompileBarrier();\
}while(0)

/**
 * @brief 添加线程到就绪链表
 * @param in_Thread 要添加的线程 不会修改此变量
 * @param in_p_temp 暂用线程指针 会修改此变量
 * @param in_Priority 占用优先级变量 会修改此变量
 * @param in_retVal 返回值
 * @return 0:添加到非头部 其他:添加到头部
 */
#define H_TS_LL_ThreadAddToReadyList(in_Thread,in_p_temp,in_Priority,in_retVal) \
do{\
  in_Thread->IsNotReady=0;\
  in_p_temp=H_TS_LL_Core_Instance.ReadyThreads;\
  oH_TS_DebugAssert(in_p_temp==NULL,"H_TS:H_TS_LL_ThreadAddToReadyList():不可能出现无就绪线程的情况(至少存在一个空闲线程)");\
  in_Priority=in_Thread->Priority;\
  if(in_p_temp->Priority<in_Priority){\
    in_p_temp=H_TS_LL_Core_Instance.SubReadyThreads;\
    in_Thread->List.Ready.IsSubReady=-1;\
    if(in_p_temp==NULL){\
      H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority=in_Priority;\
      in_Thread->List.Ready.Last=NULL;\
      in_Thread->List.Ready.Next=NULL;\
      H_TS_LL_Core_Instance.SubReadyThreads=in_Thread;\
    }else{\
      if(H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority>in_Priority){\
        H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority=in_Priority;\
      }\
      in_Thread->List.Ready.Last=NULL;\
      in_Thread->List.Ready.Next=in_p_temp;\
      in_p_temp->List.Ready.Last=in_Thread;\
      H_TS_LL_Core_Instance.SubReadyThreads=in_Thread;\
    }\
    in_retVal=0;\
  }else{\
    in_Thread->List.Ready.IsSubReady=0;\
    in_Thread->List.Ready.Last=NULL;\
    in_Thread->List.Ready.Next=in_p_temp;\
    in_p_temp->List.Ready.Last=in_Thread;\
    H_TS_LL_Core_Instance.ReadyThreads=in_Thread;\
    in_retVal=-1;\
  }\
}while(0)

/**
 * @brief 添加线程到就绪链表头部
 *        在已知线程的优先级为最高时使用
 * @param in_Thread 要添加的线程 不会修改此变量
 * @param in_p_temp 暂用线程指针 会修改此变量
 * @param in_Priority 占用优先级变量 会修改此变量
 */
#define H_TS_LL_ThreadAddToReadyListHead(in_Thread,in_p_temp,in_Priority) \
do{\
  in_Thread->IsNotReady=0;\
  in_p_temp=H_TS_LL_Core_Instance.ReadyThreads;\
  oH_TS_DebugAssert(in_p_temp==NULL,"H_TS:H_TS_LL_ThreadAddToReadyListHead():不可能出现无就绪线程的情况(至少存在一个空闲线程)");\
  oH_TS_Assert_Core(in_p_temp->Priority<in_Priority,"H_TS:H_TS_LL_ThreadAddToReadyListHead():正在运行的线程优先级是最高的, 继承的优先级也是就绪线程中最高的, 但现在有点不对劲");\
  in_Thread->List.Ready.IsSubReady=0;\
  in_Thread->List.Ready.Last=NULL;\
  in_Thread->List.Ready.Next=in_p_temp;\
  in_p_temp->List.Ready.Last=in_Thread;\
  H_TS_LL_Core_Instance.ReadyThreads=in_Thread;\
}while(0)

/**
 * @brief 固定添加线程链表到就绪链表 用来把副就绪链表的线程添加到就绪链表
 * @param Thread 要添加的线程链表
 * @return 无
 */
void H_TS_LL_ThreadListForceAddToReadyList(H_TS_Thread* Thread);

/**
 * @brief 将当前线程从就绪链表中移除
 * @param in_ThisThread 当前线程 该变量不会被修改
 * @param in_p_next 暂用线程指针 会修改此变量
 * @param in_p_last 暂用线程指针 会修改此变量
 * @return 无
 */
#define H_TS_LL_ThreadRemoteThisFromReadyList(in_ThisThread,in_p_next,in_p_last) \
do{\
  in_ThisThread->IsNotReady=-1;\
  in_p_last=in_ThisThread->List.Ready.Last;\
  in_p_next=in_ThisThread->List.Ready.Next;\
  oH_TS_Assert_Core(in_p_next==NULL,"H_TS:H_TS_LL_ThreadRemoteThisFromReadyList():至少存在一个空闲线程 要移除的线程不可能是空闲线程 即p_next不可能为NULL");\
  oH_TS_Assert_Core(in_p_last!=NULL,"H_TS:H_TS_LL_ThreadRemoteThisFromReadyList():在单核CPU中 p_last的值肯定为NULL");\
  H_TS_LL_Core_Instance.ReadyThreads=in_p_next;\
  in_p_next->List.Ready.Last=NULL;\
  in_p_last=H_TS_LL_Core_Instance.SubReadyThreads;\
  if(in_p_last!=NULL){\
    if(in_p_next->Priority>H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority){\
      H_TS_LL_Core_Instance.SubReadyThreads=NULL;\
      H_TS_LL_ThreadListForceAddToReadyList(in_p_last);\
    }\
  }\
}while(0)

/**
 * @brief 将线程从就绪链表中移除
 * @param in_Thread 线程 该变量不会被修改
 * @param in_p_next 暂用线程指针 会修改此变量
 * @param in_p_last 暂用线程指针 会修改此变量
 * @return 无
 */
#define H_TS_LL_ThreadRemoteFromReadyList(in_Thread,in_p_next,in_p_last) \
do{\
  in_Thread->IsNotReady=-1;\
  if(in_Thread->List.Ready.IsSubReady==0){\
    in_p_last=in_Thread->List.Ready.Last;\
    in_p_next=in_Thread->List.Ready.Next;\
    oH_TS_Assert_Core(in_p_next==NULL,"H_TS:H_TS_LL_ThreadRemoteFromReadyList():至少存在一个空闲线程 要移除的线程不可能是空闲线程 即p_next不可能为NULL");\
    if(in_p_last==NULL){\
      H_TS_LL_Core_Instance.ReadyThreads=in_p_next;\
    }else{\
      in_p_last->List.Ready.Next=in_p_next;\
    }\
    in_p_next->List.Ready.Last=in_p_last;\
    in_p_last=H_TS_LL_Core_Instance.SubReadyThreads;\
    if(in_p_last!=NULL){\
      if(in_p_next->Priority>H_TS_LL_Core_Instance.SubReadyThreadsHighestPriority){\
        H_TS_LL_Core_Instance.SubReadyThreads=NULL;\
        H_TS_LL_ThreadListForceAddToReadyList(in_p_last);\
      }\
    }\
  }else{\
    in_p_last=H_TS_LL_Core_Instance.SubReadyThreads;\
    oH_TS_Assert_Core(in_p_last==NULL,"H_TS:H_TS_LL_ThreadRemoteFromReadyList():线程在副就绪链表中 此段不可能为NULL");\
    H_TS_LL_Core_Instance.SubReadyThreads=NULL;\
    H_TS_LL_ThreadListForceAddToReadyList(in_p_last);\
    in_p_last=in_Thread->List.Ready.Last;\
    in_p_next=in_Thread->List.Ready.Next;\
    oH_TS_Assert_Core(in_p_next==NULL,"H_TS:H_TS_LL_ThreadRemoteFromReadyList():至少存在一个空闲线程 要移除的线程不可能是空闲线程 即_p_next不可能为NULL");\
    if(in_p_last==NULL){\
      H_TS_LL_Core_Instance.ReadyThreads=in_p_next;\
    }else{\
      in_p_last->List.Ready.Next=in_p_next;\
    }\
    in_p_next->List.Ready.Last=in_p_last;\
  }\
}while(0)

/**
 * @brief 添加线程到阻塞链表
 * @param in_Thread 要添加的线程 不会修改此变量
 * @param in_p_next 暂用线程指针 会修改此变量
 * @return 无
 */
#define H_TS_LL_ThreadAddToBlockList(in_Thread,in_p_next) \
do{\
  in_p_next=H_TS_LL_Core_Instance.BlockThreads;\
  in_Thread->List.Block.Next=in_p_next;\
  in_Thread->List.Block.Last=NULL;\
  if(in_p_next!=NULL){\
    in_p_next->List.Block.Last=in_Thread;\
  }\
  H_TS_LL_Core_Instance.BlockThreads=in_Thread;\
}while(0)

/**
 * @brief 将线程添加到睡眠(Sleep)链表
 * @param Thread 要添加的线程
 * @param NumOfTick 睡眠tick数
 * @return 无
 */
void H_TS_LL_ThreadAddToSleepList(H_TS_Thread* Thread,H_TS_Tick NumOfTick);

/**
 * @brief 将线程添加到时间限制阻塞(TimeBlock)链表
 * @param Thread 要添加的线程
 * @param Timeout 最大等待时间
 * @return 无
 */
void H_TS_LL_ThreadAddToTimeBlockList(H_TS_Thread* Thread,H_TS_Tick Timeout);




#endif //hLL_H_TS_LL_Core_H_
